package com.icongyou.enterprise.course_detail.mapper;

import com.icongyou.enterprise.course_detail.entity.AssignmentEntity;
import com.icongyou.enterprise.course_detail.entity.AssignmentRankEntity;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.jdbc.Sql;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

/**
 * 课程详情 Mapper 层测试
 * 测试 MyBatis SQL 查询和数据库交互
 * 
 * 注意：此测试需要数据库环境
 * 使用 @SpringBootTest 进行完整的集成测试
 */
@SpringBootTest
@Transactional
@DisplayName("课程详情Mapper测试")
public class CourseDetailMapperTest {

    @Autowired
    private CourseDetailMapper courseDetailMapper;

    private static final String TEST_STUDENT_ID = "660e8400-e29b-41d4-a716-446655440101";
    private static final String TEST_COURSE_ID = "aa0e8400-e29b-41d4-a716-446655440501";
    private static final String TEST_ASSIGNMENT_ID = "ee0e8400-e29b-41d4-a716-446655440901";

    @Test
    @DisplayName("测试查询学生课程任务列表 - 基本功能")
    void testGetStudentAssignmentsByCourse_BasicFunction() {
        List<AssignmentEntity> assignments = courseDetailMapper.getStudentAssignmentsByCourse(
                TEST_STUDENT_ID, TEST_COURSE_ID);

        assertNotNull(assignments, "任务列表不应为null");
        
        // 如果有数据，验证数据结构
        if (!assignments.isEmpty()) {
            AssignmentEntity firstAssignment = assignments.get(0);
            assertNotNull(firstAssignment.getAssignmentId(), "任务ID不应为null");
            assertNotNull(firstAssignment.getAssignmentName(), "任务名称不应为null");
            assertNotNull(firstAssignment.getAssignmentType(), "任务类型不应为null");
        }
    }

    @Test
    @DisplayName("测试查询学生课程任务列表 - 无数据")
    void testGetStudentAssignmentsByCourse_NoData() {
        String nonExistentStudentId = "nonexistent";
        String nonExistentCourseId = "nonexistent";

        List<AssignmentEntity> assignments = courseDetailMapper.getStudentAssignmentsByCourse(
                nonExistentStudentId, nonExistentCourseId);

        assertNotNull(assignments, "任务列表不应为null");
        assertTrue(assignments.isEmpty(), "不存在的学生课程应返回空列表");
    }

    @Test
    @DisplayName("测试查询学生课程任务列表 - 任务类型字段")
    void testGetStudentAssignmentsByCourse_TaskTypeField() {
        List<AssignmentEntity> assignments = courseDetailMapper.getStudentAssignmentsByCourse(
                TEST_STUDENT_ID, TEST_COURSE_ID);

        assertNotNull(assignments, "任务列表不应为null");
        
        // 验证所有任务都有任务类型字段
        assignments.forEach(a -> {
            assertNotNull(a.getAssignmentType(), "任务类型不应为null");
            assertTrue(a.getAssignmentType() >= 0, "任务类型应为有效值");
        });
    }

    @Test
    @DisplayName("测试查询结果不为null")
    void testGetStudentAssignmentsByCourse_ResultNotNull() {
        List<AssignmentEntity> assignments = courseDetailMapper.getStudentAssignmentsByCourse(
                TEST_STUDENT_ID, TEST_COURSE_ID);

        assertNotNull(assignments, "任务列表不应为null，即使没有数据也应返回空列表");
        
        // 验证任务类型的有效性
        assignments.forEach(a -> {
            assertTrue(a.getAssignmentType() == 0 || a.getAssignmentType() == 1, 
                "任务类型应为0（个人）或1（团队）");
        });
    }

    @Test
    @DisplayName("测试查询任务排名列表 - 基本功能")
    void testGetAssignmentRankings_BasicFunction() {
        List<AssignmentRankEntity> rankings = courseDetailMapper.getAssignmentRankings(TEST_ASSIGNMENT_ID);

        assertNotNull(rankings, "排名列表不应为null");
        
        // 如果有数据，验证数据结构
        if (!rankings.isEmpty()) {
            AssignmentRankEntity firstRank = rankings.get(0);
            assertNotNull(firstRank.getAssignmentId(), "任务ID不应为null");
            assertNotNull(firstRank.getStudentId(), "学生ID不应为null");
            assertNotNull(firstRank.getRank(), "排名不应为null");
            assertTrue(firstRank.getRank() > 0, "排名应大于0");
        }
    }

    @Test
    @DisplayName("测试查询任务排名列表 - 排序正确性")
    void testGetAssignmentRankings_SortOrder() {
        List<AssignmentRankEntity> rankings = courseDetailMapper.getAssignmentRankings(TEST_ASSIGNMENT_ID);

        assertNotNull(rankings, "排名列表不应为null");
        
        if (rankings.size() > 1) {
            // 验证排名是否按升序排列
            for (int i = 0; i < rankings.size() - 1; i++) {
                assertTrue(rankings.get(i).getRank() <= rankings.get(i + 1).getRank(),
                        "排名应该按升序排列");
            }
        }
    }

    @Test
    @DisplayName("测试查询任务排名列表 - 无数据")
    void testGetAssignmentRankings_NoData() {
        String nonExistentAssignmentId = "nonexistent";

        List<AssignmentRankEntity> rankings = courseDetailMapper.getAssignmentRankings(nonExistentAssignmentId);

        assertNotNull(rankings, "排名列表不应为null");
        assertTrue(rankings.isEmpty(), "不存在的任务应返回空排名列表");
    }

    @Test
    @DisplayName("测试查询特定学生的任务排名 - 基本功能")
    void testGetStudentAssignmentRank_BasicFunction() {
        AssignmentRankEntity rank = courseDetailMapper.getStudentAssignmentRank(
                TEST_ASSIGNMENT_ID, TEST_STUDENT_ID);

        // 可能返回null（数据不存在）或有数据
        if (rank != null) {
            assertEquals(TEST_ASSIGNMENT_ID, rank.getAssignmentId(), "任务ID应匹配");
            assertEquals(TEST_STUDENT_ID, rank.getStudentId(), "学生ID应匹配");
            assertNotNull(rank.getRank(), "排名不应为null");
            assertTrue(rank.getRank() > 0, "排名应大于0");
        }
    }

    @Test
    @DisplayName("测试查询特定学生的任务排名 - 无数据")
    void testGetStudentAssignmentRank_NoData() {
        String nonExistentAssignmentId = "nonexistent";
        String nonExistentStudentId = "nonexistent";

        AssignmentRankEntity rank = courseDetailMapper.getStudentAssignmentRank(
                nonExistentAssignmentId, nonExistentStudentId);

        assertNull(rank, "不存在的任务和学生应返回null");
    }

    @Test
    @DisplayName("测试查询特定学生的任务排名 - 学生未参与")
    void testGetStudentAssignmentRank_StudentNotParticipated() {
        String nonParticipatingStudentId = "99999999-9999-9999-9999-999999999999";

        AssignmentRankEntity rank = courseDetailMapper.getStudentAssignmentRank(
                TEST_ASSIGNMENT_ID, nonParticipatingStudentId);

        // 学生未参与应返回null
        assertNull(rank, "学生未参与的任务应返回null");
    }

    @Test
    @DisplayName("测试Mapper注入和连接")
    void testMapperInjection() {
        assertNotNull(courseDetailMapper, "CourseDetailMapper应该被正确注入");
    }

    @Test
    @DisplayName("测试SQL特殊字符处理")
    void testSqlSpecialCharacters() {
        // 测试包含特殊字符的ID（不应导致SQL注入）
        String specialStudentId = "test'123"; // 包含单引号
        String specialCourseId = "test-101"; // 包含连字符

        // 应该不会抛出SQL注入异常
        assertDoesNotThrow(() -> {
            List<AssignmentEntity> assignments = courseDetailMapper.getStudentAssignmentsByCourse(
                    specialStudentId, specialCourseId);
            assertNotNull(assignments, "即使使用特殊字符，也应返回结果（可能为空）");
        }, "特殊字符不应导致SQL异常");
    }

    @Test
    @DisplayName("测试查询性能")
    void testQueryPerformance() {
        // 测试查询性能和响应时间
        long startTime = System.currentTimeMillis();
        
        List<AssignmentEntity> assignments = courseDetailMapper.getStudentAssignmentsByCourse(
                TEST_STUDENT_ID, TEST_COURSE_ID);
        
        long endTime = System.currentTimeMillis();
        long duration = endTime - startTime;

        assertNotNull(assignments, "任务列表不应为null");
        assertTrue(duration < 3000, "查询应该在3秒内完成"); // 性能检查
    }

    @Test
    @DisplayName("测试NULL参数处理")
    void testNullParameters() {
        // 测试传入null参数时的行为
        assertDoesNotThrow(() -> {
            List<AssignmentEntity> assignments = courseDetailMapper.getStudentAssignmentsByCourse(null, null);
            assertNotNull(assignments, "即使参数为null，也应返回空列表而不是null");
        });

        assertDoesNotThrow(() -> {
            List<AssignmentRankEntity> rankings = courseDetailMapper.getAssignmentRankings(null);
            assertNotNull(rankings, "即使参数为null，也应返回空列表而不是null");
        });

        assertDoesNotThrow(() -> {
            courseDetailMapper.getStudentAssignmentRank(null, null);
            // 可以返回null，不需要验证结果
        });
    }

    @Test
    @DisplayName("测试空字符串参数处理")
    void testEmptyStringParameters() {
        // 测试传入空字符串时的行为
        List<AssignmentEntity> assignments = courseDetailMapper.getStudentAssignmentsByCourse("", "");
        assertNotNull(assignments, "空字符串参数应返回空列表");
        assertTrue(assignments.isEmpty(), "空字符串参数应返回空列表");

        List<AssignmentRankEntity> rankings = courseDetailMapper.getAssignmentRankings("");
        assertNotNull(rankings, "空字符串参数应返回空列表");
        assertTrue(rankings.isEmpty(), "空字符串参数应返回空列表");
    }

    @Test
    @DisplayName("测试并发查询")
    void testConcurrentQueries() throws InterruptedException {
        // 测试多线程并发查询的正确性和线程安全性
        final boolean[] success = {true, true, true};
        
        Thread thread1 = new Thread(() -> {
            try {
                List<AssignmentEntity> assignments = courseDetailMapper.getStudentAssignmentsByCourse(
                        TEST_STUDENT_ID, TEST_COURSE_ID);
                assertNotNull(assignments);
            } catch (Exception e) {
                success[0] = false;
            }
        });

        Thread thread2 = new Thread(() -> {
            try {
                List<AssignmentRankEntity> rankings = courseDetailMapper.getAssignmentRankings(TEST_ASSIGNMENT_ID);
                assertNotNull(rankings);
            } catch (Exception e) {
                success[1] = false;
            }
        });

        Thread thread3 = new Thread(() -> {
            try {
                courseDetailMapper.getStudentAssignmentRank(TEST_ASSIGNMENT_ID, TEST_STUDENT_ID);
            } catch (Exception e) {
                success[2] = false;
            }
        });

        thread1.start();
        thread2.start();
        thread3.start();

        thread1.join();
        thread2.join();
        thread3.join();

        // 验证所有线程都成功执行
        assertTrue(success[0] && success[1] && success[2], "并发查询应该全部成功");
    }
}
